package top.purity.server.tenant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.persistence.criteria.Predicate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import top.purity.framework.common.exception.ServiceException;
import top.purity.framework.orm.PageResp;
import top.purity.server.tenant.controller.vo.AddTenantUserReqVO;
import top.purity.server.tenant.controller.vo.TenantInfoVO;
import top.purity.server.tenant.controller.vo.TenantTableReqVO;
import top.purity.server.tenant.controller.vo.UpdateTenantUserReqVO;
import top.purity.server.tenant.domain.TenantUser;
import top.purity.server.tenant.domain.repository.TenantUserRepository;
import top.purity.server.tenant.feign.input.UserFeign;
import top.purity.server.tenant.feign.input.dto.AddUserDTO;
import top.purity.server.tenant.service.TenantUserService;
import top.purity.server.tenant.service.convert.TenantUserConvert;
import org.springframework.stereotype.Service;

import java.awt.print.Book;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @version 1.0
 * @Author Lmh
 * @Description
 * @CreateTime 2023-09-22 22:29
 */

@Service
@Slf4j
@RequiredArgsConstructor
public class TenantUserServiceImpl implements TenantUserService {

    private final TenantUserRepository tenantUserRepository;

    private final UserFeign userFeign;

    @Override
    public TenantInfoVO getInfo(Long id) {
        TenantUser tenantUser = tenantUserRepository.getReferenceById(id);
        return TenantUserConvert.INSTANCE.convertToTenantInfoVo(tenantUser);
    }

    @Override
    public void add(AddTenantUserReqVO vo) {
        TenantUser tenantUser = TenantUserConvert.INSTANCE.convertToDo(vo);
        tenantUserRepository.save(tenantUser);

        // 新增用户
        AddUserDTO addUserDTO = new AddUserDTO();
        addUserDTO.setTenantId(tenantUser.getId().toString());
        addUserDTO.setUsername(vo.getRootAdminAccount());
        addUserDTO.setPassword(vo.getRootPass());
        // TODO 利用 mq 做异步处理，处理失败则手动回滚
        userFeign.addUserByAddTenant(addUserDTO);
    }

    @Override
    public PageResp<TenantInfoVO> table(TenantTableReqVO reqVO) {
        PageRequest pageRequest = PageRequest.of(reqVO.getPageNo() - 1, reqVO.getPageSize());

        // 组装查询条件
        Specification<TenantUser> specification = (item, query, cb) -> {
            // 根据 status 查询
            List<Predicate> predicateList = new ArrayList<>();
            if (ObjUtil.isNotEmpty(reqVO.getStatus())) {
                Predicate status = cb.equal(item.get("status"), reqVO.getStatus());
                predicateList.add(status);
            }

            // 根据 status 查询
            if (StrUtil.isNotBlank(reqVO.getTenantCode())) {
                Predicate status = cb.equal(item.get("tenantCode"), reqVO.getTenantCode());
                predicateList.add(status);
            }

            // 转换成arr
            Predicate[] array = predicateList.toArray(new Predicate[]{});
            return cb.and(array);
        };


        Specification<TenantUser> tenantUserSpecification = Specification.allOf(specification);
        Page<TenantUser> all = tenantUserRepository.findAll(tenantUserSpecification, pageRequest);
        List<TenantUser> list = all.toList();

        List<TenantInfoVO> tenantInfoVOS = new ArrayList<>();
        for (TenantUser tenantUser : list) {
            TenantInfoVO tenantInfoVO = TenantUserConvert.INSTANCE.convertToTenantInfoVo(tenantUser);
            TenantInfoVO.BaseInfo baseInfo = TenantUserConvert.INSTANCE.convertToTenantInfoBaseInfoVo(tenantUser);
            tenantInfoVO.setTenant(baseInfo);
            TenantInfoVO.AddrInfo addrInfo = TenantUserConvert.INSTANCE.convertToTenantInfoAddrInfoVo(tenantUser);
            tenantInfoVO.setFunc(addrInfo);

            tenantInfoVOS.add(tenantInfoVO);
        }
        return new PageResp<>(all.getTotalElements(), tenantInfoVOS);
    }

    @Override
    public void update(UpdateTenantUserReqVO vo) throws ServiceException {
        Optional<TenantUser> byId = tenantUserRepository.findById(vo.getId());
        TenantUser tenantUser = byId.orElseThrow(() -> new ServiceException("不存在的租户"));
        BeanUtil.copyProperties(vo, tenantUser);
        tenantUserRepository.save(tenantUser);
    }
}
